import xbmcaddon,xbmcgui,hashlib,re,sys,traceback,time
from follwitAPI import FollwitAPI
from xbmcInterface import FollwitXBMCInterface

import time

class FollwitAddon():
    def __init__(self):
        self.settings = xbmcaddon.Addon(id='script.follwit')
        self.language = self.settings.getLocalizedString
        self.username = self.settings.getSetting('username')
        self.password = self.settings.getSetting('password')
        if self.settings.getSetting('debug') == 'true':
            self.debug = True
            print '[Follwit Addon] ***Starting Addon Class***'
        else:
            self.debug = False
        self.follwitAPI = FollwitAPI(self.username, self.password, self.debug)
        self.xbmcInt = FollwitXBMCInterface(self.debug)
        self.getXBMCMovies()
        self.getXBMCEpisodes()
        print '[Follwit Addon] Debug Value: ' + str(self.debug)
    
    # Method verifies username and password are in settings.
    # checks to see if password is hashed (if not hashes it)
    def verifySettings(self):
        if self.username == '':
            xbmcgui.Dialog().ok("Follw.it Service", self.language(2100).encode( "utf-8", "ignore" )) # please enter your Username and Password in settings
            self.settings.openSettings()
            self.username = self.settings.getSetting('username')
            self.password = self.settings.getSetting('password')
            return False
        elif self.password == '':
            xbmcgui.Dialog().ok("Follw.it Service", self.language(2100).encode( "utf-8", "ignore" )) # please enter your Username and Password in settings
            self.settings.openSettings()
            self.password = self.settings.getSetting('password')
            return False
        self.checkPassword()
        return True
    
    # method to hash a password and replace the current settings password with the hashed one
    def hashPassword(self):
        if self.password == '':
            return
        salt = '52c3a0d0-f793-46fb-a4c0-35a0ff6844c8'
        password = self.password
        
        hash = hashlib.sha1()
        saltedPassword = password + salt
        hash.update(saltedPassword)
        saltedPassword = hash.hexdigest()
        self.password = saltedPassword
        self.settings.setSetting('password', self.password)
        
    # Method that determines if the password has already been converted to a hash
    def checkPassword(self):
        findHash = re.compile('[0-9a-f]{40}')
        isHashed = findHash.match(self.password)
        
        if isHashed == None:
            if self.debug:
                print self.language(2101) # hashing password
            self.hashPassword()
        
    
    def getXBMCMovies(self):
        result = self.xbmcInt.getAllMovies()
        self.movieCount = result['result']['limits']['total']
        if self.movieCount > 0:
            self.xbmcMovies = result['result']['movies']
        
    def getXBMCEpisodes(self):
        result = self.xbmcInt.getAllEpisodes()
        self.episodeCount = result['result']['limits']['total']
        if self.episodeCount > 0:
            self.xbmcEpisodes = result['result']['episodes']
            self.getXBMCTVShows()
            
    def getXBMCTVShows(self):
        result = self.xbmcInt.getAllTVShows()
        self.tvshowCount = result['result']['limits']['total']
        if self.tvshowCount > 0:
            temp = {}
            for item in result['result']['tvshows']:
                temp[item['tvshowid']] = item['imdbnumber']
            self.xbmcTvShows = temp
    
    #generator to split an array into seperate arrays of size n
    def chunks(self, input, n):
        # Yield successive n-sized chunks from input.
        for i in xrange(0, len(input), n):
            yield input[i:i+n]

    # Method to sync all movies in library with Follwit
    # if follwit shows the item as watched, XBMC flags the item as watched
    def syncMovies(self):
        self.follwitAPI.clearQueue()
        self.getXBMCMovies()
        tempBulk = {}
        tempBulk['movies'] = []
        for xbmcMovie in self.xbmcMovies:
            if not xbmcMovie['imdbnumber'] == '':
                temp = {}
                temp['resources'] = 'imdb.com='+xbmcMovie['imdbnumber']
                temp['in_collection'] = True
                temp['client_id'] = xbmcMovie['movieid']
                if xbmcMovie['playcount'] > 0:
                    temp['watched'] = True
                tempBulk['movies'].append(temp)
        
        # follwit bulk requests have a max of 75 items per request
        movieChunks = list(self.chunks(tempBulk['movies'], 75))
        numChunks = len(movieChunks)
        if self.debug:
            print '[Follwit Addon] Number of movie chunks to sync: ' + str(numChunks)
        
        for chunk in movieChunks:                
            apiBulk = {}
            apiBulk['movies'] = chunk
            self.follwitAPI.remoteAPI('POST', 'movie/bulk_action', apiBulk, True)
        
        progress = xbmcgui.DialogProgress()
        progress.create("Follw.it Addon", self.language(2104).encode( "utf-8", "ignore" ))
        i = 0
        timeout = 0
        while i < numChunks:
            if timeout > 30:
                if self.debug:
                    print '[Follwit Addon] Sync timeout responce exceeded. Terminating Sync.'
                return
            if progress.iscanceled():
                xbmcgui.Dialog().ok("Follw.it Addon", self.language(2103).encode( "utf-8", "ignore" )) # Progress Aborted
                return
            if self.follwitAPI.responseQueue.empty():
                time.sleep(1)
                timeout = timeout+1
                continue
            else:
                timeout = 0
                response = self.follwitAPI.responseQueue.get()
                i=i+1
                if self.debug:
                    print '[Follwit Addon] Processing chunk: ' + str(i) +'/'+str(numChunks)
                progress.update(100 / numChunks * i)
                if not response == False:
                    for item in response:
                        if item['watched'] == True and self.xbmcInt.isWatchedMovie(item['client_id']) == False:
                            self.xbmcInt.setWatchedMovie(item['client_id'])
                else:
                    print '[Follwit Addon] Error in bulk movie request'

    
    # Method to sync all episodes in library with Follwit
    # if follwit shows the item as watched, XBMC flags the item as watched
    def syncEpisodes(self):
        self.follwitAPI.clearQueue()
        self.getXBMCEpisodes()
        tempBulk = {}
        tempBulk['episodes'] = []
        for xbmcEpisode in self.xbmcEpisodes:
            if not xbmcEpisode['tvshowid'] == '' and not xbmcEpisode['episode'] == '' and not xbmcEpisode['season'] == '':
                temp = {}
                temp['in_collection'] = True
                temp['client_id'] = xbmcEpisode['episodeid']
                temp['tvdb_series_id'] = self.xbmcTvShows[xbmcEpisode['tvshowid']]
                temp['season_number'] = xbmcEpisode['season']
                temp['episode_number'] = xbmcEpisode['episode']
                
                if xbmcEpisode['playcount'] > 0:
                    temp['watched'] = True
                tempBulk['episodes'].append(temp)
        
        # follwit bulk requests have a max of 75 items per request
        episodeChunks = list(self.chunks(tempBulk['episodes'], 75))
        numChunks = len(episodeChunks)
        if self.debug:
            print '[Follwit Addon] Number of episode chunks to sync: ' + str(numChunks)
            
        for chunk in episodeChunks:
            apiBulk = {}
            apiBulk['episodes'] = chunk
            self.follwitAPI.remoteAPI('POST', 'episode/bulk_action', apiBulk, True)
        
        progress = xbmcgui.DialogProgress()
        progress.create("Follw.it Addon", self.language(2105).encode( "utf-8", "ignore" ))
        i = 0
        timeout = 0
        while i < numChunks:
            if timeout > 30:
                if self.debug:
                    print '[Follwit Addon] Sync timeout responce exceeded. Terminating Sync.'
                return
            if progress.iscanceled():
                xbmcgui.Dialog().ok("Follw.it Addon", self.language(2103).encode( "utf-8", "ignore" )) # Progress Aborted
                return
            if self.follwitAPI.responseQueue.empty():
                time.sleep(1)
                timeout = timeout+1
                continue
            else:
                timeout = 0
                response = self.follwitAPI.responseQueue.get()
                i=i+1
                if self.debug:
                    print '[Follwit Addon] Processing chunk: ' + str(i) +'/'+str(numChunks)
                progress.update(100 / numChunks * i)
                if not response == False:
                    for item in response:
                        if item['watched'] == True and self.xbmcInt.isWatchedEpisode(item['client_id']) == False:
                            self.xbmcInt.setWatchedEpisode(item['client_id'])
                else:
                    print '[Follwit Addon] Error in bulk episode request'
                
    

